/**
 * 
 */
package com.da.landlord;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.googlecode.cswish.annotation.Rest;
import com.googlecode.cswish.exception.ApplicationException;
import com.googlecode.cswish.oosearch.Condition;
import com.googlecode.cswish.struts.ServletRedirectResult;
import com.googlecode.cswish.struts.spring.GenericService;
import com.googlecode.cswish.struts.spring.ObjectFactory;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.util.ValueStack;
import com.ra.external.RoomInfoService;
import com.ra.external.RoomRetrievalService;
import com.ra.external.ServiceInfoService;
import com.ra.landlord.Building;
import com.ra.landlord.BuildingFloor;
import com.ra.landlord.FeeRule;
import com.ra.landlord.FeeRuleCfg;
import com.ra.landlord.LandlordAssistUser;
import com.ra.landlord.LandlordOwnerUser;
import com.ra.landlord.LandlordUser;
import com.ra.landlord.LandlordUserService;
import com.ra.landlord.Room;
import com.ra.landlord.RoomConfig;
import com.ra.landlord.RoomService;
import com.ra.landlord.Zone;
import com.ra.util.Address;
import com.ra.util.AddressService;

/**
 * 批量房源管理
 * @author Jebel Qin
 * @date 2015年8月6日
 * @since v4.0
 */

@Service
public class RoomSourceService
{
	public static final Integer COPY_TO_ALL_FLOOR = 0;
	
	private static final Log logger = LogFactory.getLog(RoomSourceService.class);
	
	@Resource
	private GenericService genericService;
	
	@Resource
	private LandlordUserService landlordUserService;
	
	@Resource
	private AddressService addressService;
	
	@Resource
	private ServiceInfoService serviceInfoService;
	
	@Resource
	private RoomService roomService;
	
	@Resource
	private RoomRetrievalService roomRetrievalService;
	
	@Resource
	private RoomInfoService roomInfoService;
	
	private RoomSourceService roomSourceService;
	
	private RoomSourceService getThis()
	{
		if (roomSourceService == null)
		{
			roomSourceService = ObjectFactory.getInstance().getBean(RoomSourceService.class, false);
		}
		return roomSourceService;
	}
	
	/**
	 * 批量增加房间
	 * @param model
	 */
	@Rest(type="add")
	public Result batchAdd(Building model, List<Integer> feeRuleCfg, List<String> floorName)
	{
		Building addedBuilding = getThis().batchAddInTrans(model, feeRuleCfg, floorName);
		
		//发布房源
		roomRetrievalService.batchPublishRooms(addedBuilding.getRooms(), false);
		
		Result result = new ServletRedirectResult("/da/landlord/roomSource._updateRooms.html?buildingId=" + addedBuilding.getId());
		ObjectFactory.getInstance().autoWireBean(result);
		return result;
	}
	
	@Transactional
	public Building batchAddInTrans(Building model, List<Integer> feeRuleCfg, List<String> floorName)
	{
		int totalRooms = model.getFloorCount() * model.getRoomsPerFloor();
		if(totalRooms > 1000)
		{
			logger.warn("batchAddRooms: Create room count more than 1000 one time.");
			throw new ApplicationException("一次批量创建房间不能超过1000套！");
		}
		
		//设置默认缺省值
		model.setRentCycle(0);    //缴费周期: 1月
		model.setRentPayMode(0);  //押付模式: 一压一付

		LandlordUser loginUser =  landlordUserService.getLoginUser();
		LandlordOwnerUser ownerUser = loginUser.getOwnerUser();
		LandlordOwnerUser landlordOwnerUser = genericService.load(loginUser.getOwnerUser());
		model.setPhoneNum(landlordOwnerUser.getPhone());
		
		List<LandlordUser> landlordUsers = new ArrayList<>();
		//model.setLandlordUser(landlordOwnerUser);
		landlordUsers.add(landlordOwnerUser);
		if (loginUser instanceof LandlordAssistUser)
		{
			landlordUsers.add(loginUser);
		}
		model.setLandlordUsers(landlordUsers);
		
		if (landlordOwnerUser.getBuildings() == null) {
			landlordOwnerUser.setBuildings(new ArrayList<Building>());
		}
		//landlordOwnerUser.getBuildings().add(model);
		model.setRoomCount(0);  //老代码
		
		//新增的地址同时，给出一个区域，该区域待优化，应该给一个默认省市区域相同的区域
		Zone zone = null;
		Address address = model.getAddress();
		address = addressService.completeAddress(address);
		zone = addressService.getZone(address);
		if (zone != null) 
		{
			address.setZone1(zone);
		}
		else
		{
			// 给个默认的区域
			zone = new Zone();
			String zoneName = addressService.getFirstAddress(model.getAddress());
			zone.setName(zoneName);
			address.setZone1(zone);
		}
		
		model.setDetailAddress(address.getName());
		int floorCount = model.getFloorCount();
		int roomCountPerFloor = model.getRoomsPerFloor();
		
		List<BuildingFloor> buildingFloors = new ArrayList<BuildingFloor>(floorCount);
		List<Room> rooms = new ArrayList<Room>(floorCount * roomCountPerFloor);
		int rentType = Building.RENT_TYPE_ENTIRE; //model.getRentType();
		int floorNameSize = floorName.size();
		for (int floorIndex = 0; floorIndex < floorCount ; floorIndex++)
		{
			int floorNo = floorIndex + 1;
			
			String curFloorName = null;
			if (floorNameSize > floorIndex)
			{
				curFloorName = floorName.get(floorIndex); 
			}
			curFloorName = StringUtils.isEmpty(curFloorName) ? String.valueOf(floorNo) : curFloorName;   //"第"+floorNo+"层"
			
			BuildingFloor buildingFloor = new BuildingFloor();
			buildingFloor.setNo(floorNo);
			buildingFloor.setName(curFloorName);
			buildingFloor.setBuilding(model);
			buildingFloor.setType(0);  // 老代码: 默认为0，暂不知作何用
//			buildingFloor.setLandlordUser(landlordOwnerUser);
//			buildingFloor.setStatus(status);
			for (int roomIndex = 0; roomIndex < roomCountPerFloor; roomIndex++)
			{
				int roomNo = roomIndex + 1;
				String roomNoStr = roomNo < 10 ? ("0"+ roomNo) : String.valueOf(roomNo);
				String roomName = floorNo + roomNoStr;
				
				Room room = new Room();
				room.setBuilding(model);
//				room.setLandlordUser(landlordOwnerUser);
				
				room.setBuildingFloor(buildingFloor);
				
				room.setRental("1000");
				room.setRentType(rentType);
				room.setNo(String.valueOf(roomNo));
				room.setName(roomName);
				room.setAddress(address);
				room.setRentState(Room.RENT_STATE_NOYET);
				//room.setRoomType(4);//1, 2, 4
				room.setRoomCount(2);
				room.setHallCount(1);
				room.setToiletCount(1);
				room.adaptRoomTypeNew();
				room.setPurpose(0);
				room.setArea(BigDecimal.valueOf(100));
//				room.setConfig(config);
//				room.setOrientation(orientation);
				
				RoomConfig roomConfig = new RoomConfig();
				if (Boolean.TRUE.equals(model.getElevator()))
				{
					roomConfig.setElevator(true);
				}
				room.setRoomConfig(roomConfig);
				//同步配置老字段
				roomService.fillRoomConfig(room);
				if (!feeRuleCfg.isEmpty())
				{
					List<FeeRule> feeRules = new ArrayList<FeeRule>(3);
					for (Integer ruleCfgId : feeRuleCfg)
					{
						FeeRule feeRule = new FeeRule();
						FeeRuleCfg dbFeeRuleCfg = genericService.load(FeeRuleCfg.class, ruleCfgId);
						feeRule.setFeeRuleCfg(dbFeeRuleCfg);
						feeRule.setRoom(room);
//						feeRule.setLandlordUser(landlordOwnerUser);
						feeRules.add(feeRule);
					}
					room.setFeeRules(feeRules);
				}
				
				
				rooms.add(room);
			}

			buildingFloors.add(buildingFloor);
		}
		model.setRooms(rooms);
		model.setBuildingFloors(buildingFloors);
		Building addedBuilding = genericService.add(model);
		
		//注: 一下代码保证房东对管理员加入的楼房有权限
		if (loginUser instanceof LandlordAssistUser) {
			landlordOwnerUser.getBuildings().add(addedBuilding);
			addedBuilding.getLandlordUsers().add(landlordOwnerUser);
			genericService.merge(landlordOwnerUser);
		}
//		serviceInfoService.batchAddServiceInfosFromBaidu(addedBuilding.getId());
		
		return addedBuilding;
	}
	
	/**
	 * 批量管理房源，获取指定楼层的楼栋和房间信息
	 * @param buildingId
	 * @param floor
	 * @return
	 */
	@Rest(type="_update")
	public Building _updateRooms(Integer buildingId, Integer floor)
	{
		Building building = genericService.load(Building.class, buildingId);
		List<BuildingFloor> floors = building.getBuildingFloors();
		
		BuildingFloor theFloor = null;
		for (BuildingFloor buildingFloor : floors)
		{
			if (buildingFloor.getId().equals(floor))
			{
				theFloor = buildingFloor;
			}
		}
		if (theFloor == null)
		{
			theFloor = floors.get(0);
		}
		Room example = new Room();
		example.setBuildingFloor(theFloor);
		List<Room> rooms = genericService.searchAll(example, false).getData();
		//List<Room> rooms = genericService.search(example, 0, 0, "no", "ASC", false, null, null, false, false).getData();
		building.setRooms(rooms);
		
		ValueStack valueStack = ActionContext.getContext().getValueStack();
		valueStack.setValue("curFloorName", theFloor.getName());
		valueStack.setValue("curFloor", theFloor.getId());
		valueStack.set("floorSize", floors.size());
		
		return building;
	}
	
	/**
	 *  批量修改房间
	 * @param buildingId
	 * @param floor
	 * @param rooms
	 * @return
	 */
	@Rest(type="update")
	public Result updateRooms(Integer buildingId, Integer floor, List<Room> rooms)
	{
		List<Room> updatedRooms = getThis().doUpdateRooms(buildingId, floor, rooms);
		
		//发布房源
		roomRetrievalService.batchPublishRooms(updatedRooms, false);
		
		Result result = new ServletRedirectResult("/da/landlord/roomSource._updateRooms.html?buildingId=" + buildingId + "&floor=" + floor);
		ObjectFactory.getInstance().autoWireBean(result);
		return result;
	}
	
	@Transactional
	public List<Room> doUpdateRooms(Integer buildingId, Integer floor, List<Room> rooms)
	{
		List<Room> updatedRooms = new ArrayList<Room>(rooms.size());
		for (Room room : rooms)
		{
			Room dbRoom = genericService.load(Room.class, room.getId());
			dbRoom.setName(room.getName());
			dbRoom.setRental(room.getRental());
			dbRoom.setDepositNum(room.getDepositNum());
			dbRoom.setPayNum(room.getPayNum());
			dbRoom.setRoomCount(room.getRoomCount());
			dbRoom.setHallCount(room.getHallCount());
			dbRoom.setToiletCount(room.getToiletCount());
			dbRoom.adaptRoomTypeNew();
			dbRoom.setArea(room.getArea());
			dbRoom.setOrientation(room.getOrientation());
			
			//TODO set other info. e.g. FeeRuleCfg
			List<FeeRule> feeRules = room.getFeeRules();
			List<FeeRule> dbFeeRules = dbRoom.getFeeRules();
			autoSetUpdatedFeeRules(dbRoom, feeRules, dbFeeRules);
			
			RoomConfig dbRoomConfig = dbRoom.getRoomConfig();
			RoomConfig roomConfig = room.getRoomConfig();
			if (dbRoomConfig == null && roomConfig != null)
			{
				dbRoom.setRoomConfig(roomConfig);
			}
			else if (dbRoomConfig != null && roomConfig == null)
			{
				dbRoomConfig.clearValues();
			}
			else if (dbRoomConfig != null && roomConfig != null)
			{
				BeanUtils.copyProperties(roomConfig, dbRoomConfig, new String[]{"id"});
			}
			
			//同步配置老字段
			roomService.fillRoomConfig(dbRoom);
			genericService.merge(dbRoom);
			
			updatedRooms.add(dbRoom);
		}
		
		return updatedRooms;
	}
	
	private void autoSetUpdatedFeeRules(Room room, List<FeeRule> newFeeRules, List<FeeRule> dbFeeRules)
	{
		if (newFeeRules != null && !newFeeRules.isEmpty())
		{
			//Note: Must set the room to relation to FeeRule
			for (FeeRule feeRule : newFeeRules)
			{
				feeRule.setRoom(room);
			}
		}
		
		if (dbFeeRules.isEmpty() && (newFeeRules != null && !newFeeRules.isEmpty()))
		{
			//新增
			//dbRoom.setFeeRules(feeRules);  //Note: Can not to set new list to replace original empty list.
			dbFeeRules.addAll(newFeeRules);
		}
		else if (!dbFeeRules.isEmpty() && (newFeeRules == null || newFeeRules.isEmpty()))
		{
			//删除
			dbFeeRules.clear();
		}
		else if (!dbFeeRules.isEmpty() && (newFeeRules != null && !newFeeRules.isEmpty()))
		{
			//修改
			List<FeeRule> removedList = getRemovedFeeRuls(newFeeRules, dbFeeRules);
			dbFeeRules.removeAll(removedList);
			List<FeeRule> addedList = getAddedFeeRuls(newFeeRules, dbFeeRules);
			dbFeeRules.addAll(addedList);
		}
	}
	
	private List<FeeRule> getRemovedFeeRuls(List<FeeRule> feeRules, List<FeeRule> dbFeeRules)
	{
		List<FeeRule> removedList = new ArrayList<FeeRule>(5);
		for (FeeRule dbFeeRule : dbFeeRules)
		{
			if (!checkIsExistFeeRuleList(feeRules, dbFeeRule))
			{
				removedList.add(dbFeeRule);
			}
		}
		
		return removedList;
	}
	
	private List<FeeRule> getAddedFeeRuls(List<FeeRule> feeRules, List<FeeRule> dbFeeRules)
	{
		List<FeeRule> addedList = new ArrayList<FeeRule>(5);
		for (FeeRule feeRule : feeRules)
		{
			if (!checkIsExistFeeRuleList(dbFeeRules, feeRule))
			{
				addedList.add(feeRule);
			}
		}
		
		return addedList;
	}
	
	private boolean checkIsExistFeeRuleList(List<FeeRule> feeRules, FeeRule dbFeeRule)
	{
		boolean exist = false;
		for (FeeRule feeRule : feeRules)
		{
			if (feeRule.getFeeRuleCfg().getId().equals(dbFeeRule.getFeeRuleCfg().getId()))
			{
				exist = true;
				break;
			}
		}
		return exist;
	}
	
	/**
	 * 批量删除房间
	 * @param buildingId
	 * @param floor
	 * @param rooms
	 * @return
	 */
	@Rest(type="delete")
	public Result deleteRooms(Integer buildingId, Integer floor, List<Room> rooms)
	{
		List<Integer> roomIds = getThis().doDeleteRooms(buildingId, floor, rooms);
		
		//同步WebRent 删除房源
		roomInfoService.batchDeleteRooms(roomIds);
		
		Result result = new ServletRedirectResult("/da/landlord/roomSource._updateRooms.html?buildingId=" + buildingId + "&floor=" + floor);
		ObjectFactory.getInstance().autoWireBean(result);
		return result;
	}
	
	@Transactional
	public List<Integer> doDeleteRooms(Integer buildingId, Integer floor, List<Room> rooms)
	{
		List<Room> willDeleteList = new ArrayList<Room>(rooms.size());
		List<Integer> roomIds = new ArrayList<Integer>(rooms.size());
		for (Room room : rooms)
		{
			if (room.getId() == null)
			{
				continue;
			}
			willDeleteList.add(room);
			
			roomIds.add(room.getId());
		}
		
		roomService.deleteRoom(willDeleteList);
		
		return roomIds;
	}
	
	/**
	 * Copy指定楼层的房间信息
	 * @param buildingId
	 * @param floor
	 * @param toFloor
	 * @return
	 */
	@Rest(type="update")
	public Boolean copyBuildingFloor(Integer buildingId, Integer floor, String toFloor)
	{
		String[] toFloors = toFloor.split(",");
		List<Integer> toFloorList = new ArrayList<Integer>(toFloors.length);
		for (String toFloorStr : toFloors) 
		{
			toFloorList.add(Integer.valueOf(toFloorStr));
		}
		List<Room> allUpdatedList = getThis().doCopyBuildingFloor(buildingId, floor, toFloorList);
		
		//发布房源
		roomRetrievalService.batchPublishRooms(allUpdatedList, false);
		return true;
	}
	
	@Transactional
	public List<Room> doCopyBuildingFloor(Integer buildingId, Integer floor, List<Integer> toFloor)
	{
		if (buildingId == null || floor == null || toFloor == null || toFloor.isEmpty())
		{
			logger.error("Can not to doCopyBuildingFloor as incorrect parameters. buildingId:"+ buildingId + "|floor:" + floor + "|toFloor:"+toFloor);
			throw new ApplicationException("无效的请求！");
		}
		List<Room> fromList = getRoomsByFloorId(floor);
		List<Room> allUpdatedList = new ArrayList<Room>();
		for (Integer floorId : toFloor) {
			List<Room> toList = getRoomsByFloorId(floorId);
			List<Room> updatedList = copyFloorRoomAndSave(fromList, toList);
			allUpdatedList.addAll(updatedList);
		}

		return allUpdatedList;
	}
	
	/**
	 * Copy楼房层的房间并保存到DB
	 * @param fromList
	 * @param toList
	 */
	private List<Room> copyFloorRoomAndSave(List<Room> fromList, List<Room> toList)
	{
		Room toRoom;
		List<Room> updatedList = new ArrayList<Room>(toList.size());
		for (Room fromRoom : fromList)
		{
			if (StringUtils.isBlank(fromRoom.getNo()))
			{
				continue;
			}
			
			if (fromRoom.getName().equals(fromRoom.getNo()))
			{
				toRoom = getRoomByRoomSubNo(fromRoom.getNo(), toList);
			}
			else
			{
				toRoom = getRoomByRoomNo(fromRoom.getNo(), toList);
			}
			
			if (toRoom == null)
			{
				continue;
			}
			copyRoomData(fromRoom, toRoom);
			Room upatedRoom = genericService.update(toRoom);
			
			updatedList.add(upatedRoom);
		}
		
		return updatedList;
	}
	
	private Room getRoomByRoomSubNo(String roomNo, List<Room> rooms)
	{
		if (roomNo.length() < 2)
		{
			return null;
		}
		String subNo;
		if (roomNo.length() == 2)
		{
			subNo = roomNo.substring(1);
		}
		else
		{
			subNo = roomNo.substring(roomNo.length() - 2);
		}
		Room result = null;
		for (Room room : rooms) 
		{
			if (subNo.equals(room.getNo().substring(room.getNo().length() - 2)))
			{
				result = room;
				break;
			}
		}
		return result;
	}
	
	private Room getRoomByRoomNo(String roomNo, List<Room> rooms)
	{
		Room result = null;
		for (Room room : rooms) 
		{
			if (roomNo.equals(room.getNo()))
			{
				result = room;
				break;
			}
		}
		return result;
	}
	
	/**
	 * Copy房间数据
	 * @param fromRoom
	 * @param toRoom
	 */
	private void copyRoomData(Room fromRoom, Room toRoom)
	{
		toRoom.setRental(fromRoom.getRental());
		toRoom.setDepositNum(fromRoom.getDepositNum());
		toRoom.setPayNum(fromRoom.getPayNum());
		toRoom.setRoomCount(fromRoom.getRoomCount());
		toRoom.setHallCount(fromRoom.getHallCount());
		toRoom.setToiletCount(fromRoom.getToiletCount());
		toRoom.adaptRoomTypeNew();
		toRoom.setArea(fromRoom.getArea());
		toRoom.setOrientation(fromRoom.getOrientation());
		//TODO copy other info.
		
		List<FeeRule> newFeeRules = new ArrayList<FeeRule>(3);
		
		List<FeeRule> fromFeeRuls = fromRoom.getFeeRules();
		for (FeeRule feeRule : fromFeeRuls)
		{
			FeeRule newFeeRule = new FeeRule();
			newFeeRule.setFeeRuleCfg(feeRule.getFeeRuleCfg());
			newFeeRules.add(newFeeRule);
		}
		List<FeeRule> dbFeeRuls  = toRoom.getFeeRules();
		
		autoSetUpdatedFeeRules(toRoom, newFeeRules, dbFeeRuls);
		
		//--
		RoomConfig dbRoomConfig = toRoom.getRoomConfig();
		RoomConfig roomConfig = fromRoom.getRoomConfig();
		if (dbRoomConfig == null && roomConfig != null)
		{
			dbRoomConfig = new RoomConfig();
			//BeanUtils.copyProperties(roomConfig, dbRoomConfig, new String[]{"id"}); //No any effect
			copyRoomConfig(roomConfig, dbRoomConfig);
			toRoom.setRoomConfig(dbRoomConfig);
		}
		else if (dbRoomConfig != null && roomConfig == null)
		{
			dbRoomConfig.clearValues();
		}
		else if (dbRoomConfig != null && roomConfig != null)
		{
			//BeanUtils.copyProperties(roomConfig, dbRoomConfig, new String[]{"id"}); //No any effect
			copyRoomConfig(roomConfig, dbRoomConfig);
		}
		
		//同步配置老字段
		roomService.fillRoomConfig(toRoom);
	}
	
	private void copyRoomConfig(RoomConfig from, RoomConfig to)
	{
		to.setBed(from.getBed());
		to.setBalcony(from.getBalcony());
		to.setHeater(from.getHeater());
		to.setGas(from.getGas());
		to.setBroadband(from.getBroadband());
		to.setFreezer(from.getFreezer());
		to.setAirCondition(from.getAirCondition());
		to.setTv(from.getTv());
		to.setWashingMachine(from.getWashingMachine());
		to.setDesk(from.getDesk());
		to.setArmoire(from.getArmoire());
		to.setToilet(from.getToilet());
		to.setKitchen(from.getKitchen());
		to.setElevator(from.getElevator());
	}
	
	/**
	 * 根据楼层ID获取楼层的所有的房间
	 * @param floorId
	 * @return
	 */
	private List<Room> getRoomsByFloorId(Integer floorId)
	{
		BuildingFloor queryModel = new BuildingFloor();
		queryModel.setId(floorId);
		BuildingFloor buildingFloor = genericService.load(queryModel, false);
		
		return getRoomsByBuildingFloor(buildingFloor);
	}
	
	/**
	 * 根据楼层对象获取楼层的所有的房间
	 * @param buildingFloor
	 * @return
	 */
	private List<Room> getRoomsByBuildingFloor(BuildingFloor buildingFloor)
	{
		Room queryRoom = new Room();
		queryRoom.setBuildingFloor(buildingFloor);
		Condition condition = new Condition();
		condition.setSort("no");
		condition.setDir("asc");
		return genericService.searchByModel(queryRoom, condition, false, false).getData();
	}
	
}
